--[[
LysButtons

This little addon lets you set buttons for food/drink that auto update outside of combat for your consumables.

]]


------------------------------------------------------------------------------------------------
-- Core Program Functions - this program can't run without these.
------------------------------------------------------------------------------------------------
function LCB_OnLoad(frame)
	-- Register the variables loaded event...
	frame:RegisterEvent("ADDON_LOADED");
	frame:RegisterEvent("PLAYER_ENTERING_WORLD");
	frame:RegisterEvent("PLAYER_LEAVING_WORLD");

	-- Register our slash commands
	SLASH_LCB1 = "/lcb";
	SLASH_LCB2 = "/lysbuttons";
	SlashCmdList["LCB"] = function(msg)
		LCB_SlashCommandHandler(msg);
	end
end

function LCB_OnEvent(frame,event,...)
	if ((event == "ADDON_LOADED") and (select(1, ...) == "LysButtons")) then
		if (LCB_VERSION_NUM ~= nil) then
			DEFAULT_CHAT_FRAME:AddMessage(LCB_VERSION.." loaded.");
		end
		LCB_DataConfig();
		LCB_RegConfig();

	elseif (event == "PLAYER_ENTERING_WORLD") then
		-- What events should we listen for?
		frame:RegisterEvent("BAG_UPDATE");
		frame:RegisterEvent("BAG_UPDATE_COOLDOWN");
		frame:RegisterEvent("ITEM_LOCK_CHANGED");
		frame:RegisterEvent("ITEM_UNLOCKED");
		--frame:RegisterEvent("PLAYER_LEAVE_COMBAT");
		frame:RegisterEvent("PLAYER_REGEN_ENABLED");

		if (not LCB_Config.enabled) then
			return;
		end
		
		if (not LCB_Config.login) then
			return;
		end

		LCB_GetConsumables();
		LCB_UpdateHealthButton();
		LCB_UpdateManaButton();
		LCB_UpdateBandageButton();
		LCB_UpdateHealthPotButton();
		LCB_UpdateManaPotButton();

	elseif (event == "PLAYER_REGEN_ENABLED") then
		if (not LCB_Config.enabled) then
			return;
		end

		if (not LCB_Config.combat) then
			return;
		end

		LCB_GetConsumables();
		LCB_UpdateHealthButton();
		LCB_UpdateManaButton();
		LCB_UpdateBandageButton();
		LCB_UpdateHealthPotButton();
		LCB_UpdateManaPotButton();

	-- Respond to all the events above.
	else
		if (not LCB_Config.enabled) then
			return;
		end

		LCB_GetConsumables();
	end
end


------------------------------------------------------------------------------------------------
-- Internal program functions
------------------------------------------------------------------------------------------------
function LCB_SlashCommandHandler(msg)
	InterfaceOptionsFrame_OpenToCategory(LCB_GUI);
end


-- Set the tooltip display
function LCB_SetTooltip(tooltip)
	local _;

	tooltip:AddLine(LCB_DESC, 1.0, 1.0, 1.0);
	tooltip:AddLine(" ");

	local subType, itemLink;

	for subType in pairs(LCB_CONSUMABLE_LIST) do
		tooltip:AddLine(subType);

		-- List off the items for this subtype
		for itemLink in pairs(LCB_CONSUMABLE_LIST[subType]) do
			tooltip:AddDoubleLine(itemLink, LCB_CONSUMABLE_LIST[subType][itemLink]["count"], 0.8, 0.8, 1.0);
		end

		tooltip:AddLine(" ");
	end
end


-- Update the "Health" Button
function LCB_UpdateHealthButton()
	if (LCB_Config.HealthSlot == "0") then
		return
	end
	
	local LCB_ACTIONSLOT_HEALTH = tonumber(LCB_Config.HealthSlot);

	if (LCB_VERBOSE == 1) then
		DEFAULT_CHAT_FRAME:AddMessage("LCB: Updating Health Regen Action Button.");
	end

	local max_total		= 0;

	-- Clear the slot before we do anything with it.
	PickupAction(LCB_ACTIONSLOT_HEALTH);
	ClearCursor();

	if (LCB_CONSUMABLE_LIST["Food & Drink"] == nil) then
		return
	end

	for itemLink in pairs(LCB_CONSUMABLE_LIST["Food & Drink"]) do
		local usestring = LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["use"];
		if (usestring ~= nil) then
			if (LCB_DEBUG == 1) then
				DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Food/Drink with a use string of: "..usestring);
			end

			-- Foods that restore both health and mana
			if (string.find(usestring, "Use: Restores [,%d]+ health and [,%d]+ mana over %d+ sec.") ~= nil) then
				if (LCB_DEBUG == 1) then
					DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: usestring: "..usestring);
				end
				if (string.find(usestring, "If you spend at least") == nil) then
					if (LCB_DEBUG == 1) then
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: usestring: "..usestring);
					end
					local healpersec	= 0;
					local total, bdgTime	= string.match(usestring, "Use: Restores ([,%d]+) health and [,%d]+ mana over (%d+) sec.");

					if (total ~= nil) then
						total = string.gsub(total, ",", "");
						total = tonumber(total);

						if (total ~= nil) then
							healpersec = total / bdgTime;

							if (LCB_DEBUG == 1) then
								DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: "..total.."/"..bdgTime.." = "..healpersec..", Current Best is "..max_total);
							end

							if (healpersec > max_total) then
								local bag	= LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["bag"];
								local slot	= LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["slot"]

								if (LCB_DEBUG == 1) then
									DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Food & Drink in bag "..bag..", slot "..slot..".");
								end

								PickupContainerItem(bag, slot);
								PlaceAction(LCB_ACTIONSLOT_HEALTH);
								ClearCursor();
						
								max_total = healpersec;
							end
						end
					end
				end
			end

			-- Foods that restore only health
			if (string.find(usestring, "Use: Restores [,%d]+ health over %d+ sec.") ~= nil) then
				if (LCB_DEBUG == 1) then
					DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: usestring: "..usestring);
				end
				
				if (string.find(usestring, "If you spend at least") == nil) then
					if (LCB_DEBUG == 1) then
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: usestring: "..usestring);
					end
				
					local healpersec	= 0;
					local total, bdgTime	= string.match(usestring, "Use: Restores ([,%d]+) health over (%d+) sec.");

					if (total ~= nil) then
						total = string.gsub(total, ",", "");
						total = tonumber(total);

						if (total ~= nil) then
							healpersec = total / bdgTime;

							if (LCB_DEBUG == 1) then
								DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: "..total.."/"..bdgTime.." = "..healpersec..", Current Best is "..max_total);
							end

							if (healpersec > max_total) then
								local bag	= LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["bag"];
								local slot	= LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["slot"]

								if (LCB_DEBUG == 1) then
									DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Food & Drink in bag "..bag..", slot "..slot..".");
								end

								PickupContainerItem(bag, slot);
								PlaceAction(LCB_ACTIONSLOT_HEALTH);
								ClearCursor();
						
								max_total = healpersec;
							end
						end
					end
				end
			end
		end
	end
end

-- Update the "Mana" button
function LCB_UpdateManaButton()
	if (LCB_Config.ManaSlot == "0") then
		return
	end
	
	local LCB_ACTIONSLOT_MANA = tonumber(LCB_Config.ManaSlot);

	if (LCB_VERBOSE == 1) then
		DEFAULT_CHAT_FRAME:AddMessage("LCB: Updating Mana Regen Action Button.");
	end

	local max_total		= 0;

	-- Clear the slot before we do anything with it.
	PickupAction(LCB_ACTIONSLOT_MANA);
	ClearCursor();

	if (LCB_CONSUMABLE_LIST["Food & Drink"] == nil) then
		return
	end

	for itemLink in pairs(LCB_CONSUMABLE_LIST["Food & Drink"]) do
		local usestring = LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["use"];
		if (usestring ~= nil) then
			if (LCB_DEBUG == 1) then
				DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Food/Drink with a use string of: "..usestring);
			end

			-- Foods that restore both health and mana
			if (string.find(usestring, "Use: Restores [,%d]+ health and [,%d]+ mana over %d+ sec.") ~= nil) then
				if (LCB_DEBUG == 1) then
					DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: usestring: "..usestring);
				end
				if (string.find(usestring, "If you spend at least") == nil) then
					local healpersec	= 0;
					local total, bdgTime	= string.match(usestring, "Use: Restores [,%d]+ health and ([,%d]+) mana over (%d+) sec.");

					if (total ~= nil) then
						total = string.gsub(total, ",", "");
						total = tonumber(total);

						if (total ~= nil) then
							healpersec = total / bdgTime;

							if (LCB_DEBUG == 1) then
								DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: "..total.."/"..bdgTime.." = "..healpersec..", Current Best is "..max_total);
							end

							if (healpersec > max_total) then
								local bag	= LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["bag"];
								local slot	= LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["slot"]

								if (LCB_DEBUG == 1) then
									DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Food & Drink in bag "..bag..", slot "..slot..".");
								end

								PickupContainerItem(bag, slot);
								PlaceAction(LCB_ACTIONSLOT_MANA);
								ClearCursor();
						
								max_total = healpersec;
							end
						end
					end
				end
			end

			-- Mana Only foods
			if (string.find(usestring, "Use: Restores [,%d]+ mana over %d+ sec.") ~= nil) then
				if (LCB_DEBUG == 1) then
					DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: usestring: "..usestring);
				end
				if (string.find(usestring, "If you spend at least") == nil) then
					local healpersec	= 0;
					local total, bdgTime	= string.match(usestring, "Use: Restores ([,%d]+) mana over (%d+) sec.");

					if (total ~= nil) then
						total = string.gsub(total, ",", "");
						total = tonumber(total);

						if (total ~= nil) then
							healpersec = total / bdgTime;

							if (LCB_DEBUG == 1) then
								DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: "..total.."/"..bdgTime.." = "..healpersec..", Current Best is "..max_total);
							end

							if (healpersec > max_total) then
								local bag	= LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["bag"];
								local slot	= LCB_CONSUMABLE_LIST["Food & Drink"][itemLink]["slot"]

								if (LCB_DEBUG == 1) then
									DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Food & Drink in bag "..bag..", slot "..slot..".");
								end

								PickupContainerItem(bag, slot);
								PlaceAction(LCB_ACTIONSLOT_MANA);
								ClearCursor();
						
								max_total = healpersec;
							end
						end
					end
				end
			end
		end
	end
end

-- Update the "Bandages" Button
function LCB_UpdateBandageButton()
	if (LCB_Config.BandageSlot == "0") then
		return
	end
	
	local LCB_ACTIONSLOT_BANDAGE = tonumber(LCB_Config.BandageSlot);

	if (LCB_VERBOSE == 1) then
		DEFAULT_CHAT_FRAME:AddMessage("LCB: Updating Bandage Action Button.");
	end

	local max_total		= 0;

	-- Clear the slot before we do anything with it.
	PickupAction(LCB_ACTIONSLOT_BANDAGE);
	ClearCursor();

	if (LCB_CONSUMABLE_LIST["Bandage"] == nil) then
		return
	end

	-- Update the slot
	for itemLink in pairs(LCB_CONSUMABLE_LIST["Bandage"]) do
		local usestring = LCB_CONSUMABLE_LIST["Bandage"][itemLink]["use"];
		if (usestring ~= nil) then
			if (LCB_DEBUG == 1) then
				DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found a Bandage with a use string of: "..usestring);
			end

			if (string.find(usestring, "Use: Heals ") ~= nil) then
				local healpersec	= 0;
				local total, bdgTime	= string.match(usestring, "Heals (.+) damage over (%d+) sec");

				if (total ~= nil) then
					total = string.gsub(total, ",", "");
					total = tonumber(total);
					
					healpersec = total / bdgTime;

					if (LCB_DEBUG == 1) then
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Total = "..total);
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Total Per Second = "..healpersec);
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Max Total = "..max_total);
					end

					if (healpersec > max_total) then
						local bag	= LCB_CONSUMABLE_LIST["Bandage"][itemLink]["bag"];
						local slot	= LCB_CONSUMABLE_LIST["Bandage"][itemLink]["slot"]

						if (LCB_DEBUG == 1) then
							DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Bandage in bag "..bag..", slot "..slot..".");
						end

						PickupContainerItem(bag, slot);
						PlaceAction(LCB_ACTIONSLOT_BANDAGE);
						ClearCursor();
						
						max_total = healpersec;
					end
				end
			end
		end
	end
end

-- Update the "Health Potion" Button
function LCB_UpdateHealthPotButton()
	if (LCB_Config.HealthPotionSlot == "0") then
		return
	end
	
	local LCB_ACTIONSLOT_HEALTHPOT = tonumber(LCB_Config.HealthPotionSlot);

	if (LCB_VERBOSE == 1) then
		DEFAULT_CHAT_FRAME:AddMessage("LCB: Updating Health Potion Action Button.");
	end

	local max_total = 0;

	-- Clear the slot before we do anything with it.
	PickupAction(LCB_ACTIONSLOT_HEALTHPOT);
	ClearCursor();

	if (LCB_CONSUMABLE_LIST["Potion"] == nil) then
		return
	end
	
	-- Update the slot
	for itemLink in pairs(LCB_CONSUMABLE_LIST["Potion"]) do
		local usestring = LCB_CONSUMABLE_LIST["Potion"][itemLink]["use"];
		if (usestring ~= nil) then
			if (LCB_DEBUG == 1) then
				DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found a Potion with a use string of: "..usestring);
			end

			if (string.find(usestring, "Use: Restores .+ health.") ~= nil) then
				local total = string.match(usestring, "Use: Restores (.+) health.");

				if (total ~= nil) then
					total = string.gsub(total, ",", "");
					total = string.gsub(total, " .+", "");
					total = tonumber(total);

					if (LCB_DEBUG == 1) then
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Total = "..total);
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Max Total = "..max_total);
					end

					if (total > max_total) then
						local bag	= LCB_CONSUMABLE_LIST["Potion"][itemLink]["bag"];
						local slot	= LCB_CONSUMABLE_LIST["Potion"][itemLink]["slot"]

						if (LCB_DEBUG == 1) then
							DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Potion in bag "..bag..", slot "..slot..".");
						end

						PickupContainerItem(bag, slot);
						PlaceAction(LCB_ACTIONSLOT_HEALTHPOT);
						ClearCursor();
						
						max_total = total;
					end
				end
			end
		end
	end
end

-- Update the "Mana Potion" Button
function LCB_UpdateManaPotButton()
	if (LCB_Config.ManaPotionSlot == "0") then
		return
	end
	
	local LCB_ACTIONSLOT_MANAPOT = tonumber(LCB_Config.ManaPotionSlot);

	if (LCB_VERBOSE == 1) then
		DEFAULT_CHAT_FRAME:AddMessage("LCB: Updating Mana Potion Action Button.");
	end

	local max_total = 0;

	-- Clear the slot before we do anything with it.
	PickupAction(LCB_ACTIONSLOT_MANAPOT);
	ClearCursor();

	if (LCB_CONSUMABLE_LIST["Potion"] == nil) then
		return
	end
	
	-- Update the slot
	for itemLink in pairs(LCB_CONSUMABLE_LIST["Potion"]) do
		local usestring = LCB_CONSUMABLE_LIST["Potion"][itemLink]["use"];
		if (usestring ~= nil) then
			if (LCB_DEBUG == 1) then
				DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found a Potion with a use string of: "..usestring);
			end

			if (string.find(usestring, "Use: Restores .+ mana.") ~= nil) then
				local total = string.match(usestring, "Use: Restores (.+) mana.");

				if (total ~= nil) then
					total = string.gsub(total, ",", "");
					total = string.gsub(total, " .+", "");
					total = tonumber(total);
				
					if (LCB_DEBUG == 1) then
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Total = "..total);
						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Max Total = "..max_total);
					end

					if (total > max_total) then
						local bag	= LCB_CONSUMABLE_LIST["Potion"][itemLink]["bag"];
						local slot	= LCB_CONSUMABLE_LIST["Potion"][itemLink]["slot"]

						if (LCB_DEBUG == 1) then
							DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: Found Potion in bag "..bag..", slot "..slot..".");
						end

						PickupContainerItem(bag, slot);
						PlaceAction(LCB_ACTIONSLOT_MANAPOT);
						ClearCursor();
						
						max_total = total;
					end
				end
			end
		end
	end
end



-- Get the list of consumables in inventory
function LCB_GetConsumables()
	local myBag;

	-- Empty the consumables list
	LCB_CONSUMABLE_LIST = {};
	
	-- Show tally for each bag seperately
	for myBag = 0, 4 do
		-- Check if the bag actually has any slots as we don't want to do cash tallies of bag slots with no bag in them.
		local mySlot;
		local slotCount = GetContainerNumSlots(myBag);

		if ( slotCount > 0) then
			for mySlot = 0, slotCount do
--				local itemId	= GetContainerItemID(myBag, mySlot);
				local itemLink	= GetContainerItemLink(myBag, mySlot);
				
				if (itemLink ~= nil) then
					local _,itemCount	= GetContainerItemInfo(myBag, mySlot);
					local itemName, _, _, _, _, itemType, itemSubType, _, _, _, _	= GetItemInfo(itemLink);

--					DEFAULT_CHAT_FRAME:AddMessage(itemLink.." itemType: "..itemType);

					if (itemType == "Consumable") then
						if (itemSubType == nil) then
							itemSubType = "Consumable";
						end

						if (LCB_CONSUMABLE_LIST[itemSubType] == nil) then
							LCB_CONSUMABLE_LIST[itemSubType] = {};
						end

						if (LCB_CONSUMABLE_LIST[itemSubType][itemLink] == nil) then
							LCB_CONSUMABLE_LIST[itemSubType][itemLink] = {};
						end

						LCB_CONSUMABLE_LIST[itemSubType][itemLink]["bag"]	= myBag;
						LCB_CONSUMABLE_LIST[itemSubType][itemLink]["slot"]	= mySlot;
						LCB_CONSUMABLE_LIST[itemSubType][itemLink]["count"]	= itemCount;
--						LCB_CONSUMABLE_LIST[itemSubType][itemLink]["link"]	= itemLink;
						LCB_CONSUMABLE_LIST[itemSubType][itemLink]["name"]	= itemName;
						LCB_CONSUMABLE_LIST[itemSubType][itemLink]["use"]	= LCB_GetItemTooltipLine(myBag, mySlot, "Use:");
--						DEFAULT_CHAT_FRAME:AddMessage("LCB Debug: "..itemLink.." Count: "..itemCount);
					end
				end
			end
		end
	end
end


-- Function: Find the tooltip line which contains itemString
function LCB_GetItemTooltipLine(itemBag, itemSlot, itemString)
	local lineIndex		= 1;
	local tooltipLine	= nil;

	-- "Own" the LCB_ToolTip
	LCB_ToolTip:SetOwner(LCB_Frame);
	LCB_ToolTip:SetBagItem(itemBag, itemSlot);

	local myCheckLine = getglobal("LCB_ToolTipTextLeft"..lineIndex);
	while (myCheckLine) do
		local myText = myCheckLine:GetText();

		if (myText ~= nil) then
			if (string.find(myText, itemString) ~= nil) then
				tooltipLine = myText;
				LCB_ToolTip:Hide();
				return tooltipLine;
			end
		end

		lineIndex = lineIndex + 1;
		myCheckLine = getglobal("LCB_ToolTipTextLeft"..lineIndex);
	end
	LCB_ToolTip:Hide();
	return tooltipLine;
end

-- Function: Set up the base program data
function LCB_DataConfig()
	if (not LCB_Config) then
		LCB_Config = {};
	end
	
	if (not LCB_Config.enabled) then
		LCB_Config.enabled		= false;
	end

	if (not LCB_Config.login) then
		LCB_Config.login		= false;
	end

	if (not LCB_Config.combat) then
		LCB_Config.combat		= false;
	end

	if (not LCB_Config.HealthSlot) then
		LCB_Config.HealthSlot		= "0";
	end

	if (not LCB_Config.ManaSlot) then
		LCB_Config.ManaSlot		= "0";
	end

	if (not LCB_Config.BandageSlot) then
		LCB_Config.BandageSlot		= "0";
	end

	if (not LCB_Config.HealthPotionSlot) then
		LCB_Config.HealthPotionSlot	= "0";
	end

	if (not LCB_Config.ManaPotionSlot) then
		LCB_Config.ManaPotionSlot	= "0";
	end

end
